package com.example.authservice.serviceImpl;

import com.example.api.service.AuthService;
import com.example.api.service.OpenApiAppService;
import com.example.common.entity.OpenApiApp;
import com.example.common.entity.vo.AccessTokenVO;
import com.example.common.entity.vo.AppInfoVO;
import com.example.common.entity.AccessTokenBody;
import com.example.common.exception.BaseException;
import com.example.common.exception.ExceptionCode;
import com.example.common.mapper.OpenApiAppMapper;
import com.example.common.utils.AccessTokenUtils;
import com.example.common.utils.StringUtils;
import com.example.common.utils.WillingAESUtils;
import lombok.SneakyThrows;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.concurrent.TimeUnit;

/**
 * @author Destinycc
 */
@Service(protocol = "dubbo")
public class AuthServiceImpl implements AuthService {
    @Reference
    OpenApiAppService openApiAppService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @SneakyThrows
    @Override
    public AccessTokenVO genAccessToken(AppInfoVO appInfo, String tenantId, Boolean forceRefresh) {
        String appId = appInfo.getAppId();
        OpenApiApp innerApp = openApiAppService.getAppByAppIdAndSecret(appId, WillingAESUtils.encrypt(appInfo.getAppSecret()));
        if (innerApp == null) {
            throw new BaseException(ExceptionCode.PARAM_NOT_VALID);
        }
        // 校验appid
        String tokenNew = getAccessTokenNew(appId);
        if (!forceRefresh) {
            //不强制刷新
            if (StringUtils.isNotEmpty(tokenNew)) {
                return new AccessTokenVO(tokenNew, getAccessTokenExpire(appId));
            }
        } else {
            //强制刷新
            if (StringUtils.isNotEmpty(tokenNew)) {
                setAccessTokenOld(appId, tokenNew);
            }
        }
        return new AccessTokenVO(genAccessToken(appInfo, tenantId), 7200);
    }

    @Override
    public String getAccessTokenNew(String appId) {
        if (StringUtils.isEmpty(appId)){
            return null;
        }
        return stringRedisTemplate.opsForValue().get(AccessTokenUtils.getTokenKey(appId));
    }

    @Override
    public String getAccessTokenOld(String appId) {
        if (StringUtils.isEmpty(appId)){
            return null;
        }
        return stringRedisTemplate.opsForValue().get(AccessTokenUtils.getTokenKey(appId) + "_old");
    }

    private void setAccessTokenNew(String appId, String token){
        stringRedisTemplate.opsForValue().set(AccessTokenUtils.getTokenKey(appId), token, 7200, TimeUnit.SECONDS);
    }

    private void setAccessTokenOld(String appId, String token){
        stringRedisTemplate.opsForValue().set(AccessTokenUtils.getTokenKey(appId) + "_old", token, 300, TimeUnit.SECONDS);
    }

    private int getAccessTokenExpire(String appId){
        return (int) (stringRedisTemplate.getExpire(AccessTokenUtils.getTokenKey(appId)) / 1000);
    }

    @SneakyThrows
    private String genAccessToken(AppInfoVO appInfo, String tenantId) {
        AccessTokenBody tokenBody = new AccessTokenBody(StringUtils.genRandomStr(4), appInfo.getAppId(), tenantId, System.currentTimeMillis());
        String accessToken = AccessTokenUtils.encrypt(tokenBody);
        setAccessTokenNew(appInfo.getAppId(), accessToken);
        return accessToken;
    }




}
